package services

import (
	"fmt"
	"regexp"
	"strings"
)

// SmartExtractService 智能字段提取服务
type SmartExtractService struct {
	fieldMappingService *FieldMappingService
}

// NewSmartExtractService 创建智能字段提取服务
func NewSmartExtractService(fieldMappingService *FieldMappingService) *SmartExtractService {
	return &SmartExtractService{
		fieldMappingService: fieldMappingService,
	}
}

// ExtractFields 从OCR结果中智能提取匹配模板字段的内容
func (s *SmartExtractService) ExtractFields(templateID string, ocrData map[string]interface{}, ocrText string) (map[string]string, error) {
	// 首先尝试使用字段映射
	mappedData, err := s.fieldMappingService.ApplyMapping(templateID, ocrData)
	if err == nil && len(mappedData) > 0 {
		return mappedData, nil
	}

	// 如果没有映射规则或映射失败，使用智能匹配
	result := make(map[string]string)

	// 获取模板变量列表
	template, err := s.getTemplateVariables(templateID)
	if err != nil {
		return result, err
	}

	// 从OCR数据中匹配
	for _, varName := range template {
		value := s.matchVariable(varName, ocrData, ocrText)
		if value != "" {
			result[varName] = value
		}
	}

	return result, nil
}

// getTemplateVariables 获取模板变量列表（这里需要访问TemplateService，暂时简化处理）
func (s *SmartExtractService) getTemplateVariables(templateID string) ([]string, error) {
	// 这里应该从TemplateService获取，暂时返回空
	// 实际使用时，需要传入变量列表
	return []string{}, nil
}

// ExtractFieldsWithVariables 从OCR结果中提取指定变量的内容
func (s *SmartExtractService) ExtractFieldsWithVariables(templateID string, variables []string, ocrData map[string]interface{}, ocrText string) (map[string]string, error) {
	result := make(map[string]string)

	// 首先尝试使用字段映射
	mappedData, err := s.fieldMappingService.ApplyMapping(templateID, ocrData)
	if err == nil {
		// 只保留模板中需要的变量
		for _, varName := range variables {
			if value, exists := mappedData[varName]; exists {
				result[varName] = value
			}
		}
	}

	// 对于未匹配到的变量，使用智能匹配
	for _, varName := range variables {
		if _, exists := result[varName]; exists {
			continue // 已经通过映射获取到了
		}

		value := s.matchVariable(varName, ocrData, ocrText)
		if value != "" {
			result[varName] = value
		}
	}

	return result, nil
}

// matchVariable 匹配单个变量
func (s *SmartExtractService) matchVariable(varName string, ocrData map[string]interface{}, ocrText string) string {
	// 方法1：直接从OCR数据中查找（键名匹配）
	if value, exists := ocrData[varName]; exists {
		return fmt.Sprintf("%v", value)
	}

	// 方法2：模糊匹配键名
	for key, value := range ocrData {
		if s.isSimilar(key, varName) {
			return fmt.Sprintf("%v", value)
		}
	}

	// 方法3：从文本中提取（使用正则表达式）
	patterns := s.generatePatterns(varName)
	for _, pattern := range patterns {
		re := regexp.MustCompile(pattern)
		matches := re.FindStringSubmatch(ocrText)
		if len(matches) > 1 {
			return strings.TrimSpace(matches[1])
		}
	}

	return ""
}

// isSimilar 判断两个字符串是否相似（简单的相似度判断）
func (s *SmartExtractService) isSimilar(s1, s2 string) bool {
	s1 = strings.ToLower(strings.TrimSpace(s1))
	s2 = strings.ToLower(strings.TrimSpace(s2))

	// 完全匹配
	if s1 == s2 {
		return true
	}

	// 包含关系
	if strings.Contains(s1, s2) || strings.Contains(s2, s1) {
		return true
	}

	// 去除常见后缀后匹配
	suffixes := []string{"姓名", "名称", "地址", "电话", "日期", "金额", "编号"}
	for _, suffix := range suffixes {
		s1Clean := strings.TrimSuffix(s1, suffix)
		s2Clean := strings.TrimSuffix(s2, suffix)
		if s1Clean == s2Clean && s1Clean != "" {
			return true
		}
	}

	return false
}

// generatePatterns 为变量名生成匹配模式
func (s *SmartExtractService) generatePatterns(varName string) []string {
	patterns := []string{}

	// 模式1: "变量名：值" 或 "变量名:值"
	patterns = append(patterns, fmt.Sprintf(`(?i)%s[：:]\s*([^\n\r]+)`, regexp.QuoteMeta(varName)))
	
	// 模式2: "变量名 值"（空格分隔）
	patterns = append(patterns, fmt.Sprintf(`(?i)%s\s+([^\n\r]+)`, regexp.QuoteMeta(varName)))

	// 模式3: 去除常见后缀后匹配
	suffixes := []string{"姓名", "名称", "地址", "电话", "日期", "金额", "编号"}
	for _, suffix := range suffixes {
		if strings.HasSuffix(varName, suffix) {
			baseName := strings.TrimSuffix(varName, suffix)
			patterns = append(patterns, fmt.Sprintf(`(?i)%s[：:]\s*([^\n\r]+)`, regexp.QuoteMeta(baseName)))
			patterns = append(patterns, fmt.Sprintf(`(?i)%s[：:]\s*([^\n\r]+)`, regexp.QuoteMeta(varName)))
		}
	}

	return patterns
}
